home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ########################################################################## #### #### #### The MusicBox Project #### #### ============================ #### #### #### #### MusicBoxSCSI.c #### #### #### #### Version 2.1os -- September 29, 2000 #### #### #### #### Copyright (C) 1994 Thomas Dreibholz #### #### 2000 Molbachweg 7 #### #### 51674 Wiehl #### #### Germany #### #### #### #### EMail: Dreibholz@bigfoot.com #### #### WWW: http://www.bigfoot.com/~dreibholz #### #### #### ########################################################################## */ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* MusicBox SCSI-Steuerung */ #include "MusicBox.h" extern struct Einstellungen Einstellungen; extern struct List Liste; extern struct Window *CDPlayerWnd; extern struct Gadget *CDPlayerGadgets[25]; extern struct Katalog *Katalog; extern struct DiskObject AudioCD; extern BOOL IsIconify; extern BOOL LowRes; void Wiedergabe(); void SetzeLR(); void Volumen(); void AuswurfLock(); void LeseStatus(); void Continue(); void LeereKatalog(); UBYTE LadeKatalog(); UBYTE SichereKatalog(); void ListeErstellen(); void ListeEntfernen(); struct IOExtTD *io; struct SCSICmd *scsi; struct MsgPort *port; struct Remember *Remember=NULL; struct Remember *ListRemember=NULL; UBYTE *buffer; UBYTE *sense; LONG dev=-1L; struct ListenEintrag { struct Node Node; UBYTE Text[58]; }; struct CDStatus { UBYTE pad00; UBYTE AudioStatus; UWORD Length; UBYTE FormatCode; UBYTE Flags; UBYTE Track; UBYTE Index; ULONG Adresse; ULONG RelAdresse; }; struct CDDriveInfo { UBYTE PeripheralType; UBYTE Modifier; UBYTE Version; UBYTE Flags1; UBYTE AdditionalLength; UBYTE reserved[2]; UBYTE Flags2; UBYTE Vendor[8]; UBYTE Product[16]; UBYTE Revision[4]; }; #define TOC_SIZE 804 struct TOCHeader { WORD Length; UBYTE FirstTrack; UBYTE LastTrack; }; struct TOCData { UBYTE pad01; UBYTE Flags; UBYTE TrackNumber; UBYTE pad02; LONG Adresse; }; struct TOCBlock { struct TOCHeader TOCHeader; struct TOCData TOCData[]; }; struct ModeData { UBYTE Head[4]; UBYTE Page; UBYTE PLength; UBYTE b2,b3,b4,b5; UWORD bps; UBYTE Out0; UBYTE Vol0; UBYTE Out1; UBYTE Vol1; UBYTE pad[4]; }; UBYTE PosTab[100]; UBYTE MBTab[100]; UBYTE cmd_eject[10] = { 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; UBYTE cmd_play[10] = { 0x48, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x63, 0x63, 0x00}; UBYTE cmd_stop[6] = { 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00}; UBYTE cmd_lock[6] = { 0x1e, 0x00, 0x00, 0x00, 0xff, 0x00}; UBYTE cmd_playfrom[10] = { 0x47, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; UBYTE cmd_audioOn[10] = { 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; UBYTE cmd_audioOff[10] = { 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; UBYTE cmd_status[10] = { 0x42, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00}; UBYTE cmd_driveinfo[6] = { 0x12, 0x00, 0x00, 0x00, 0x90, 0x00 }; UBYTE cmd_modesense[6] = { 0x1a, 0x00, 0x0e, 0x00, 0xfc, 0x00 }; UBYTE cmd_modeselect[6] = { 0x15, 0x10, 0x00, 0x00, sizeof(struct ModeData), 0x00 }; UBYTE cmd_readtoc[10]= { 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, TOC_SIZE>>8, TOC_SIZE & 0xff }; struct ThisCD *ThisCD; struct ThisDrive *ThisDrive; WORD SCSI(cmd,len,buf,buflen,direction) UBYTE *cmd; UBYTE *buf; LONG buflen; WORD len,direction; { Einstellungen.SCSI=1; io->io_Command=HD_SCSICMD; io->io_Data=scsi; io->io_Length=sizeof(struct SCSICmd); scsi->scsi_Data=buf; scsi->scsi_Length=buflen; scsi->scsi_Flags=SCSIF_AUTOSENSE|direction; scsi->scsi_SenseData=sense; scsi->scsi_SenseLength=18; scsi->scsi_SenseActual=0; scsi->scsi_Command=cmd; scsi->scsi_CmdLength=len; DoIO(io); if((io->io_Error>=40)&&(io->io_Error<=44)) Einstellungen.SCSI=2; else if(scsi->scsi_Status!=0) Einstellungen.SCSI=0; return(scsi->scsi_Status); } int InitSCSI(name,unit) UBYTE *name; UWORD unit; { UBYTE errtext[250]; int test; port=CreatePortA(0L,0L); if(port==NULL) { Error(GS(34,"Unable to create a message port for the SCSI driver!")); return(1); } io=CreateExtIOA(port,sizeof(struct IOExtTD)); if(io==NULL) { Error(GS(35,"Unable to create a IORequest for the SCSI driver!")); return(2); } dev=OpenDevice(name,unit,io,0); if(dev!=0) { sprintf(&errtext,GS(36,"Unable to open the SCSI driver:\n %s, Unit %d\nOpenDevice()-Error: #%d\n\n Please check the driver's name, unit number and if the drive is turned on!"), name,unit,io->io_Error); Error(&errtext); return(3); } buffer=AllocRemember(&Remember,2048,MEMF_CLEAR|MEMF_PUBLIC); scsi=AllocRemember(&Remember,sizeof(struct SCSICmd),MEMF_CLEAR|MEMF_PUBLIC); sense=AllocRemember(&Remember,18,MEMF_CLEAR|MEMF_PUBLIC); ThisCD=AllocRemember(&Remember,sizeof(struct ThisCD),MEMF_ANY); ThisDrive=AllocRemember(&Remember,sizeof(struct ThisDrive),MEMF_ANY); if((buffer==NULL)||(sense==NULL)||(scsi==NULL)||(ThisCD==NULL)||(ThisDrive==NULL)) { Error(GS(6,"Not enough memory!")); return(4); } Einstellungen.SCSI=1; test=SCSI(&cmd_driveinfo,6,buffer,sizeof(struct CDDriveInfo),SCSIF_READ); if(Einstellungen.SCSI!=1) { sprintf(&errtext,GS(37,"The SCSI-drive unit %d doesn't answer the Inquiry command\nDoIO()-Error #%d\nSCSI-Status #%d\nPlease check if the drive is turned on!"), unit,io->io_Error,scsi->scsi_Status); Error(&errtext); return(5); } if(((struct CDDriveInfo *)buffer)->PeripheralType!=0x05) { sprintf(&errtext, GS(38,"The SCSI-drive unit %d is not a CD-ROM-drive.\nDrive type: #%d"), unit,((struct CDDriveInfo *)buffer)->PeripheralType); Error(&errtext); return(6); } strncpy(&ThisDrive->Vendor,((struct CDDriveInfo *)buffer)->Vendor,8); strncpy(&ThisDrive->Product,((struct CDDriveInfo *)buffer)->Product,16); strncpy(&ThisDrive->Revision,((struct CDDriveInfo *)buffer)->Revision,4); ThisDrive->Vendor[8]=0x00; ThisDrive->Product[16]=0x00; ThisDrive->Revision[4]=0x00; if(!(strncmp(&ThisDrive->Vendor,"TOSHIBA"))) strcpy(&ThisDrive->Vendor,"Toshiba, Japan"); if(!(strncmp(&ThisDrive->Product,"CD-ROM XM-3401TA",16))) Einstellungen.Toshiba=1; return(0); } void EntferneSCSI() { if(dev==0) { SichereKatalog(); Einstellungen.Lock=0; AuswurfLock(); CloseDevice(io); } if(io) DeleteExtIOA(io); if(port) DeletePortA(port); if(ListRemember) FreeRemember(&ListRemember,TRUE); if(Remember) FreeRemember(&Remember,TRUE); } void LeseStatus() { REGISTER ULONG a,b; struct TagItem tag[2]; register struct CDStatus *cd; register struct TOCBlock *toc; register int i; if(!(SCSI(&cmd_status,10,buffer,512,SCSIF_READ))) { cd=buffer; switch(cd->AudioStatus) { case 0x11: if(!((Einstellungen.Funktion==VORLAUF)||(Einstellungen.Funktion==RUECKLAUF))) Einstellungen.Funktion=WIEDERGABE; break; case 0x12: if((Einstellungen.Funktion!=VORLAUF)&&(Einstellungen.Funktion!=RUECKLAUF)) Einstellungen.Funktion=PAUSE; break; case 0x14: case 0x13: if(Einstellungen.Auswahlmodus==LISTE) { if(Einstellungen.Track<ThisCD->Anzahl) { Einstellungen.Track++; if(Einstellungen.Track>ThisCD->Anzahl) Einstellungen.Track=1; if(Einstellungen.Track<1) Einstellungen.Track=1; Einstellungen.Funktion=STOP; Wiedergabe(); Einstellungen.Funktion=WIEDERGABE; } else { if(Einstellungen.AutoRepeat) { Einstellungen.Track=1; Wiedergabe(); Einstellungen.Funktion=WIEDERGABE; } else Einstellungen.Funktion=STOP; } } else { i=Random(ThisCD->Anzahl); Einstellungen.Track=i; Einstellungen.Funktion=STOP; Wiedergabe(); Einstellungen.Funktion=WIEDERGABE; } break; case 0x15: if(Einstellungen.Funktion==WIEDERGABE) Einstellungen.Funktion=STOP; break; } switch(Einstellungen.Funktion) { case PLUS: case MINUS: Einstellungen.Adresse=ThisCD->Track[Einstellungen.Track-1].SAdresse; Einstellungen.Funktion=STOP; break; case VORLAUF: case RUECKLAUF: break; default: if(Einstellungen.CDEingelegt) { if((cd->Track<1)||(cd->Track>ThisCD->Anzahl)) cd->Track=1; Einstellungen.Track=MBTab[cd->Track]; if(cd->Index!=0) Einstellungen.Adresse=cd->Adresse; else Einstellungen.Adresse=ThisCD->Track[Einstellungen.Track-1].SAdresse; } break; } } if(!(SCSI(&cmd_readtoc,10,buffer,TOC_SIZE,SCSIF_READ))) { if(Einstellungen.CDEingelegt==0) { Einstellungen.Funktion=STOP; Einstellungen.CDEingelegt=1; Einstellungen.CDTyp=DATEN; Einstellungen.Titel=0; toc=buffer; ThisCD->ErsterTrack=toc->TOCHeader.FirstTrack; ThisCD->LetzterTrack=toc->TOCHeader.LastTrack; ThisCD->Anzahl=0; for(i=0;i<100;i++) { PosTab[i]=0xff; MBTab[i]=0; } for(i=0;i<toc->TOCHeader.Length/8;i++) { MBTab[toc->TOCData[i].TrackNumber]=ThisCD->Anzahl+1; if((toc->TOCData[i].TrackNumber!=0xaa) && !(toc->TOCData[i].Flags & 4)) { PosTab[ThisCD->Anzahl]=toc->TOCData[i].TrackNumber; a=toc->TOCData[i].Adresse; ThisCD->Track[ThisCD->Anzahl].SMinute=(a/75/60); ThisCD->Track[ThisCD->Anzahl].SSekunde=((a/75) % 60); ThisCD->Track[ThisCD->Anzahl].SFrame=(a % 75); ThisCD->Track[ThisCD->Anzahl].SAdresse=a; b=toc->TOCData[i+1].Adresse-a; ThisCD->Track[ThisCD->Anzahl].TMinute=(b/75/60); ThisCD->Track[ThisCD->Anzahl].TSekunde=((b/75) % 60); ThisCD->Track[ThisCD->Anzahl].TFrame=(b % 75); ThisCD->Track[ThisCD->Anzahl].TAdresse=b; ThisCD->Anzahl++; Einstellungen.CDTyp=AUDIO; } } if(Einstellungen.CDTyp==DATEN) Einstellungen.Funktion=STANDBY; else { SleepPointer(CDPlayerWnd); ThisCD->Endadresse=ThisCD->Track[ThisCD->Anzahl-1].SAdresse+ThisCD->Track[ThisCD->Anzahl-1].TAdresse; ThisCD->Startadresse=ThisCD->Track[0].SAdresse; ThisCD->ID=ThisCD->Anzahl*ThisCD->Endadresse; Einstellungen.CDKatalogisiert=LadeKatalog(); ListeErstellen(); SetzeLR(); Volumen(); AuswurfLock(); Einstellungen.Track=1; Einstellungen.Adresse=0; if((Einstellungen.AutoStart)&&(Einstellungen.Funktion!=WIEDERGABE)) { Einstellungen.Funktion=AUTO; Symbol(AUTO); Einstellungen.AutoCnt=1; } ClearPointer(CDPlayerWnd); } } } else ListeEntfernen(); if(Einstellungen.Funktion==VORLAUF) { Einstellungen.Adresse+=25; if(Einstellungen.Adresse>ThisCD->Endadresse) { Einstellungen.Adresse=ThisCD->Endadresse; Einstellungen.Funktion=STOP; } a=Einstellungen.Adresse; if(Einstellungen.Track<ThisCD->Anzahl) { if(a>=ThisCD->Track[Einstellungen.Track].SAdresse) Einstellungen.Track++; } a-=ThisCD->Track[Einstellungen.Track-1].SAdresse; } else if(Einstellungen.Funktion==RUECKLAUF) { if(Einstellungen.Adresse>=25) Einstellungen.Adresse-=25; else { Einstellungen.Adresse=0; Einstellungen.Funktion=STOP; } a=Einstellungen.Adresse; if(Einstellungen.Track>1) { if(a<ThisCD->Track[Einstellungen.Track-1].SAdresse) Einstellungen.Track--; } a-=ThisCD->Track[Einstellungen.Track-1].SAdresse; } } void Auswurf() { ListeEntfernen(); SCSI(&cmd_eject,10,0,0,SCSIF_WRITE); } void Stop() { Einstellungen.Adresse=ThisCD->Track[Einstellungen.Track-1].SAdresse; SCSI(&cmd_stop,6,0,0,SCSIF_WRITE); } void Pause() { SCSI(&cmd_audioOff,10,buffer,0,SCSIF_WRITE); LeseStatus(); } void SetzeLR() { REGISTER UBYTE *m; struct ModeData modedata; register int i; for(i=0;i<4;i++) modedata.Head[i]=0; if(!(SCSI(&cmd_modesense,6,buffer,252,SCSIF_READ))) { i=buffer[3]+4; CopyMem(&buffer[i],&modedata.Page,16); modedata.Out0=Einstellungen.AudioL; modedata.Out1=Einstellungen.AudioR; SCSI(&cmd_modeselect,6,&modedata,sizeof(struct ModeData),SCSIF_WRITE); } } void Wiedergabe() { if(Einstellungen.Funktion==PAUSE) SCSI(&cmd_audioOn,10,buffer,0,SCSIF_WRITE); else if((Einstellungen.Funktion==VORLAUF)||(Einstellungen.Funktion==RUECKLAUF)) Continue(); else { Einstellungen.Adresse=ThisCD->Track[Einstellungen.Track-1].SAdresse; cmd_play[4]=PosTab[Einstellungen.Track-1]; cmd_play[7]=cmd_play[4]; cmd_play[8]=99; SCSI(&cmd_play,10,0,0,SCSIF_WRITE); } } void Continue() { REGISTER ULONG a; SCSI(&cmd_audioOff,10,buffer,0,SCSIF_WRITE); a=Einstellungen.Adresse+150; cmd_playfrom[3]=a/75/60; cmd_playfrom[4]=(a/75) % 60; cmd_playfrom[5]=a % 75; a=ThisCD->Track[Einstellungen.Track-1].TAdresse+ ThisCD->Track[Einstellungen.Track-1].SAdresse; cmd_playfrom[6]=a/75/60; cmd_playfrom[7]=(a/75) % 60; cmd_playfrom[8]=a % 75; SCSI(&cmd_playfrom,10,buffer,2048,SCSIF_WRITE); SCSI(&cmd_audioOn,10,buffer,0,SCSIF_WRITE); SetzeLR(); } void Volumen() { REGISTER UBYTE *m; struct ModeData modedata; register int i; for(i=0;i<4;i++) modedata.Head[i]=0; if(!(SCSI(&cmd_modesense,6,buffer,252,SCSIF_READ))) { i=buffer[3]+4; CopyMem(&buffer[i],&modedata.Page,16); modedata.Vol0=Einstellungen.VolumenL; modedata.Vol1=Einstellungen.VolumenR; SCSI(&cmd_modeselect,6,&modedata,sizeof(struct ModeData),SCSIF_WRITE); } } void AuswurfLock() { cmd_lock[4]=Einstellungen.Lock; SCSI(&cmd_lock,6,0,0,SCSIF_WRITE); } void ListeEntfernen() { register struct StringInfo *si; struct TagItem tag[2]; Einstellungen.CDKatalogisiert=SichereKatalog(); Einstellungen.Auswahl=255; Einstellungen.Titel=0; Einstellungen.CDEingelegt=0; Einstellungen.Funktion=STANDBY; Einstellungen.CDKatalogisiert=0; Einstellungen.NumS=0; if(ListRemember) { FreeRemember(&ListRemember,TRUE); ListRemember=NULL; NewListA(&Liste); if(IsIconify==FALSE) { si=CDPlayerGadgets[24]->SpecialInfo; strcpy(si->Buffer,""); RefreshGList(CDPlayerGadgets[24],CDPlayerWnd,NULL,1L); tag[0].ti_Tag=GTLV_Labels; tag[0].ti_Data=&Liste; tag[1].ti_Tag=TAG_DONE; GTSetGadgetAttrsA(CDPlayerGadgets[0],CDPlayerWnd,NULL,&tag); } } } void ListeErstellen() { struct TagItem tag[2]; register int i; register struct Liste *li; if(!(Einstellungen.CDEingelegt)) return; if(!(Einstellungen.CDTyp==AUDIO)) return; NewListA(&Liste); if(ListRemember) FreeRemember(&ListRemember,TRUE); ListRemember=NULL; Einstellungen.Auswahl=255; Einstellungen.Titel=0; for(i=0;i<=ThisCD->Anzahl;i++) { li=AllocRemember(&ListRemember,sizeof(struct ListenEintrag),MEMF_ANY); if(li!=NULL) { li->Node.ln_Succ=NULL; li->Node.ln_Pred=NULL; li->Node.ln_Type=0; li->Node.ln_Pri=0; li->Node.ln_Name=&li->Text; if(i<ThisCD->Anzahl) { if(LowRes==FALSE) sprintf(&li->Text,"%02d %s",i+1,&Katalog->KE[i].Titel); else sprintf(&li->Text,"%02d %s",i+1,&Katalog->KE[i].Titel); AddTail(&Liste,li); } else { sprintf(&li->Text,"%s:",&Katalog->CDName); AddHead(&Liste,li); } } } if(IsIconify==FALSE) { tag[0].ti_Tag=GTLV_Labels; tag[0].ti_Data=&Liste; tag[1].ti_Tag=TAG_DONE; GTSetGadgetAttrsA(CDPlayerGadgets[0],CDPlayerWnd,NULL,&tag); } } void LeereKatalog() { register int i; Katalog->ID[0]='D'; Katalog->ID[1]='I'; Katalog->ID[2]='S'; Katalog->ID[3]='C'; Katalog->KatalogVersion=VERSION; Katalog->Anzahl=ThisCD->Anzahl; Katalog->DiscID=ThisCD->ID; strcpy(&Katalog->CDName,"Unbenannt"); for(i=0;i<ThisCD->Anzahl;i++) { Katalog->KE[i].SAdresse=ThisCD->Track[i].SAdresse; Katalog->KE[i].TAdresse=ThisCD->Track[i].TAdresse; sprintf(&Katalog->KE[i].Titel, "Track #%d %2d:%02d'%02d", i+1, ThisCD->Track[i].TMinute, ThisCD->Track[i].TSekunde, ThisCD->Track[i].TFrame); } } UBYTE LadeKatalog() { UBYTE name[80]; register struct FileHandle *fh; register int i; sprintf(&name,"AudioCD:AudioCD-ID#%08lx",ThisCD->ID); fh=Open(&name,MODE_OLDFILE); if(fh!=NULL) { Katalog->Anzahl=99; Read(fh,Katalog,KSIZE(Katalog)); Close(fh); if(!(strncmp(&Katalog->ID,"DISC",4))) { if(ThisCD->ID==Katalog->DiscID) { /* Zeitdaten in Katalogdatei falls nötig korrigieren */ for(i=0;i<ThisCD->Anzahl;i++) { if(Katalog->KE[i].SAdresse!=ThisCD->Track[i].SAdresse) { Katalog->KE[i].SAdresse=ThisCD->Track[i].SAdresse; Einstellungen.CatChange=1; } if(Katalog->KE[i].TAdresse!=ThisCD->Track[i].TAdresse) { Katalog->KE[i].TAdresse=ThisCD->Track[i].TAdresse; Einstellungen.CatChange=1; } } /* ------------------------------------------------- */ return(1); } } } LeereKatalog(); return(0); } UBYTE SichereKatalog() { UBYTE *ttArray[5]; UBYTE name[80]; register struct DiskObject *di; register struct FileHandle *fh; if(Einstellungen.CatChange) { Einstellungen.CatChange=0; if(Einstellungen.AutoSave==0) { if(!(MultiRequest(GS(44,"Save catalog..."), GS(46,"Do you want to save the catalog?"), GS(47,"Yes, save|No!")))) return; } SleepPointer(CDPlayerWnd); sprintf(&name,"AudioCD:AudioCD-ID#%08lx",Katalog->DiscID); fh=Open(&name,MODE_NEWFILE); if(fh==NULL) return(0); Write(fh,Katalog,KSIZE(Katalog)); Close(fh); di=GetDiskObject(&name); if(di!=NULL) { AudioCD.do_CurrentX=di->do_CurrentX; AudioCD.do_CurrentY=di->do_CurrentY; FreeDiskObject(di); } ttArray[0]=&Katalog->CDName; ttArray[1]="*** This file was created by"; ttArray[2]="*** MusicBox, written by"; ttArray[3]="*** Thomas Dreibholz"; ttArray[4]=NULL; AudioCD.do_ToolTypes=&ttArray; PutDiskObject(&name,&AudioCD); ClearPointer(CDPlayerWnd); return(1); } }